home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
lisp
/
kcl
/
akcl
/
kcl.lha
/
c
/
format.c
< prev
next >
Wrap
C/C++ Source or Header
|
1987-06-04
|
43KB
|
2,083 lines
/*
(c) Copyright Taiichi Yuasa and Masami Hagiya, 1984. All rights reserved.
Copying of this file is authorized to users who have executed the true and
proper "License Agreement for Kyoto Common LISP" with SIGLISP.
*/
/*
format.c
*/
#include "include.h"
object siVindent_formatted_output;
object fmt_stream;
int ctl_origin;
int ctl_index;
int ctl_end;
object *fmt_base;
int fmt_index;
int fmt_end;
int *fmt_jmp_buf;
int fmt_indents;
object fmt_string;
#define ctl_string (fmt_string->st.st_self + ctl_origin)
#define fmt_old object old_fmt_stream; \
int old_ctl_origin; \
int old_ctl_index; \
int old_ctl_end; \
object *old_fmt_base; \
int old_fmt_index; \
int old_fmt_end; \
int *old_fmt_jmp_buf; \
int old_fmt_indents; \
object old_fmt_string
#define fmt_save old_fmt_stream = fmt_stream; \
old_ctl_origin = ctl_origin; \
old_ctl_index = ctl_index; \
old_ctl_end = ctl_end; \
old_fmt_base = fmt_base; \
old_fmt_index = fmt_index; \
old_fmt_end = fmt_end; \
old_fmt_jmp_buf = fmt_jmp_buf; \
old_fmt_indents = fmt_indents; \
old_fmt_string = fmt_string
#define fmt_restore fmt_stream = old_fmt_stream; \
ctl_origin = old_ctl_origin; \
ctl_index = old_ctl_index; \
ctl_end = old_ctl_end; \
fmt_base = old_fmt_base; \
fmt_index = old_fmt_index; \
fmt_end = old_fmt_end; \
fmt_jmp_buf = old_fmt_jmp_buf; \
fmt_indents = old_fmt_indents; \
fmt_string = old_fmt_string
#define fmt_restore1 fmt_stream = old_fmt_stream; \
ctl_origin = old_ctl_origin; \
ctl_index = old_ctl_index; \
ctl_end = old_ctl_end; \
fmt_jmp_buf = old_fmt_jmp_buf; \
fmt_indents = old_fmt_indents; \
fmt_string = old_fmt_string
object fmt_temporary_stream;
object fmt_temporary_string;
int fmt_nparam;
#define INT 1
#define CHAR 2
struct {
int fmt_param_type;
int fmt_param_value;
} fmt_param[100];
char *fmt_big_numeral[] = {
"thousand",
"million",
"billion",
"trillion",
"quadrillion",
"quintillion",
"sextillion",
"septillion",
"octillion"
};
char *fmt_numeral[] = {
"zero", "one", "two", "three", "four",
"five", "six", "seven", "eight", "nine",
"ten", "eleven", "twelve", "thirteen", "fourteen",
"fifteen", "sixteen", "seventeen", "eighteen", "nineteen",
"zero", "ten", "twenty", "thirty", "forty",
"fifty", "sixty", "seventy", "eighty", "ninety"
};
char *fmt_ordinal[] = {
"zeroth", "first", "second", "third", "fourth",
"fifth", "sixth", "seventh", "eighth", "ninth",
"tenth", "eleventh", "twelfth", "thirteenth", "fourteenth",
"fifteenth", "sixteenth", "seventeenth", "eighteenth", "nineteenth",
"zeroth", "tenth", "twentieth", "thirtieth", "fortieth",
"fiftieth", "sixtieth", "seventieth", "eightieth", "ninetieth"
};
int fmt_spare_spaces;
int fmt_line_length;
int
fmt_tempstr(s)
int s;
{
return(fmt_temporary_string->st.st_self[s]);
}
ctl_advance()
{
if (ctl_index >= ctl_end)
fmt_error("unexpected end of control string");
return(ctl_string[ctl_index++]);
}
object
fmt_advance()
{
if (fmt_index >= fmt_end)
fmt_error("arguments exhausted");
return(fmt_base[fmt_index++]);
}
format(fmt_stream0, ctl_origin0, ctl_end0)
object fmt_stream0;
int ctl_origin0;
int ctl_end0;
{
int c, i, n;
bool colon, atsign;
object x;
fmt_stream = fmt_stream0;
ctl_origin = ctl_origin0;
ctl_index = 0;
ctl_end = ctl_end0;
LOOP:
if (ctl_index >= ctl_end)
return;
if ((c = ctl_advance()) != '~') {
writec_stream(c, fmt_stream);
goto LOOP;
}
n = 0;
for (;;) {
switch (c = ctl_advance()) {
case ',':
fmt_param[n].fmt_param_type = NULL;
break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
DIGIT:
i = 0;
do {
i = i*10 + (c - '0');
c = ctl_advance();
} while (isDigit(c));
fmt_param[n].fmt_param_type = INT;
fmt_param[n].fmt_param_value = i;
break;
case '+':
c = ctl_advance();
if (!isDigit(c))
fmt_error("digit expected");
goto DIGIT;
case '-':
c = ctl_advance();
if (!isDigit(c))
fmt_error("digit expected");
i = 0;
do {
i = i*10 + (c - '0');
c = ctl_advance();
} while (isDigit(c));
fmt_param[n].fmt_param_type = INT;
fmt_param[n].fmt_param_value = -i;
break;
case '\'':
fmt_param[n].fmt_param_type = CHAR;
fmt_param[n].fmt_param_value = ctl_advance();
c = ctl_advance();
break;
case 'v': case 'V':
x = fmt_advance();
if (type_of(x) == t_fixnum) {
fmt_param[n].fmt_param_type = INT;
fmt_param[n].fmt_param_value = fix(x);
} else if (type_of(x) == t_character) {
fmt_param[n].fmt_param_type = CHAR;
fmt_param[n].fmt_param_value = x->ch.ch_code;
} else
fmt_error("illegal V parameter");
c = ctl_advance();
break;
case '#':
fmt_param[n].fmt_param_type = INT;
fmt_param[n].fmt_param_value = fmt_end - fmt_index;
c = ctl_advance();
break;
default:
if (n > 0)
fmt_error("illegal ,");
else
goto DIRECTIVE;
}
n++;
if (c != ',')
break;
}
DIRECTIVE:
colon = atsign = FALSE;
if (c == ':') {
colon = TRUE;
c = ctl_advance();
}
if (c == '@') {
atsign = TRUE;
c = ctl_advance();
}
fmt_nparam = n;
switch (c) {
case 'a': case 'A':
fmt_ascii(colon, atsign);
break;
case 's': case 'S':
fmt_S_expression(colon, atsign);
break;
case 'd': case 'D':
fmt_decimal(colon, atsign);
break;
case 'b': case 'B':
fmt_binary(colon, atsign);
break;
case 'o': case 'O':
fmt_octal(colon, atsign);
break;
case 'x': case 'X':
fmt_hexadecimal(colon, atsign);
break;
case 'r': case 'R':
fmt_radix(colon, atsign);
break;
case 'p': case 'P':
fmt_plural(colon, atsign);
break;
case 'c': case 'C':
fmt_character(colon, atsign);
break;
case 'f': case 'F':
fmt_fix_float(colon, atsign);
break;
case 'e': case 'E':
fmt_exponential_float(colon, atsign);
break;
case 'g': case 'G':
fmt_general_float(colon, atsign);
break;
case '$':
fmt_dollars_float(colon, atsign);
break;
case '%':
fmt_percent(colon, atsign);
break;
case '&':
fmt_ampersand(colon, atsign);
break;
case '|':
fmt_bar(colon, atsign);
break;
case '~':
fmt_tilde(colon, atsign);
break;
case '\n':
fmt_newline(colon, atsign);
break;
case 't': case 'T':
fmt_tabulate(colon, atsign);
break;
case '*':
fmt_asterisk(colon, atsign);
break;
case '?':
fmt_indirection(colon, atsign);
break;
case '(':
fmt_case(colon, atsign);
break;
case '[':
fmt_conditional(colon, atsign);
break;
case '{':
fmt_iteration(colon, atsign);
break;
case '<':
fmt_justification(colon, atsign);
break;
case '^':
fmt_up_and_out(colon, atsign);
break;
case ';':
fmt_semicolon(colon, atsign);
break;
default:
fmt_error("illegal directive");
}
goto LOOP;
}
fmt_skip()
{
int c, level = 0;
LOOP:
if (ctl_advance() != '~')
goto LOOP;
for (;;)
switch (c = ctl_advance()) {
case '\'':
ctl_advance();
case ',':
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
case '+':
case '-':
case 'v': case 'V':
case '#':
case ':': case '@':
continue;
default:
goto DIRECTIVE;
}
DIRECTIVE:
switch (c) {
case '(': case '[': case '<': case '{':
level++;
break;
case ')': case ']': case '>': case '}':
if (level == 0)
return(ctl_index);
else
--level;
break;
case ';':
if (level == 0)
return(ctl_index);
break;
}
goto LOOP;
}
fmt_max_param(n)
{
if (fmt_nparam > n)
fmt_error("too many parameters");
}
fmt_not_colon(colon)
bool colon;
{
if (colon)
fmt_error("illegal :");
}
fmt_not_atsign(atsign)
bool atsign;
{
if (atsign)
fmt_error("illegal @");
}
fmt_not_colon_atsign(colon, atsign)
bool colon, atsign;
{
if (colon && atsign)
fmt_error("illegal :@");
}
fmt_set_param(i, p, t, v)
int i, *p, t, v;
{
if (i >= fmt_nparam || fmt_param[i].fmt_param_type == NULL)
*p = v;
else if (fmt_param[i].fmt_param_type != t)
fmt_error("illegal parameter type");
else
*p = fmt_param[i].fmt_param_value;
}
fmt_ascii(colon, atsign)
{
int mincol, colinc, minpad, padchar;
object x;
int c, l, i;
fmt_max_param(4);
fmt_set_param(0, &mincol, INT, 0);
fmt_set_param(1, &colinc, INT, 1);
fmt_set_param(2, &minpad, INT, 0);
fmt_set_param(3, &padchar, CHAR, ' ');
fmt_temporary_string->st.st_fillp = 0;
fmt_temporary_stream->sm.sm_int0 = file_column(fmt_stream);
fmt_temporary_stream->sm.sm_int1 = file_column(fmt_stream);
x = fmt_advance();
if (colon && x == Cnil)
writestr_stream("()", fmt_temporary_stream);
else if (mincol == 0 && minpad == 0) {
princ(x, fmt_stream);
return;
} else
princ(x, fmt_temporary_stream);
l = fmt_temporary_string->st.st_fillp;
for (i = minpad; l + i < mincol; i += colinc)
;
if (!atsign) {
write_string(fmt_temporary_string, fmt_stream);
while (i-- > 0)
writec_stream(padchar, fmt_stream);
} else {
while (i-- > 0)
writec_stream(padchar, fmt_stream);
write_string(fmt_temporary_string, fmt_stream);
}
}
fmt_S_expression(colon, atsign)
{
int mincol, colinc, minpad, padchar;
object x;
int c, l, i;
fmt_max_param(4);
fmt_set_param(0, &mincol, INT, 0);
fmt_set_param(1, &colinc, INT, 1);
fmt_set_param(2, &minpad, INT, 0);
fmt_set_param(3, &padchar, CHAR, ' ');
fmt_temporary_string->st.st_fillp = 0;
fmt_temporary_stream->sm.sm_int0 = file_column(fmt_stream);
fmt_temporary_stream->sm.sm_int1 = file_column(fmt_stream);
x = fmt_advance();
if (colon && x == Cnil)
writestr_stream("()", fmt_temporary_stream);
else if (mincol == 0 && minpad == 0) {
prin1(x, fmt_stream);
return;
} else
prin1(x, fmt_temporary_stream);
l = fmt_temporary_string->st.st_fillp;
for (i = minpad; l + i < mincol; i += colinc)
;
if (!atsign) {
write_string(fmt_temporary_string, fmt_stream);
while (i-- > 0)
writec_stream(padchar, fmt_stream);
} else {
while (i-- > 0)
writec_stream(padchar, fmt_stream);
write_string(fmt_temporary_string, fmt_stream);
}
}
fmt_decimal(colon, atsign)
{
int mincol, padchar, commachar;
fmt_max_param(3);
fmt_set_param(0, &mincol, INT, 0);
fmt_set_param(1, &padchar, CHAR, ' ');
fmt_set_param(2, &commachar, CHAR, ',');
fmt_integer(fmt_advance(), colon, atsign,
10, mincol, padchar, commachar);
}
fmt_binary(colon, atsign)
{
int mincol, padchar, commachar;
fmt_max_param(3);
fmt_set_param(0, &mincol, INT, 0);
fmt_set_param(1, &padchar, CHAR, ' ');
fmt_set_param(2, &commachar, CHAR, ',');
fmt_integer(fmt_advance(), colon, atsign,
2, mincol, padchar, commachar);
}
fmt_octal(colon, atsign)
{
int mincol, padchar, commachar;
fmt_max_param(3);
fmt_set_param(0, &mincol, INT, 0);
fmt_set_param(1, &padchar, CHAR, ' ');
fmt_set_param(2, &commachar, CHAR, ',');
fmt_integer(fmt_advance(), colon, atsign,
8, mincol, padchar, commachar);
}
fmt_hexadecimal(colon, atsign)
{
int mincol, padchar, commachar;
fmt_max_param(3);
fmt_set_param(0, &mincol, INT, 0);
fmt_set_param(1, &padchar, CHAR, ' ');
fmt_set_param(2, &commachar, CHAR, ',');
fmt_integer(fmt_advance(), colon, atsign,
16, mincol, padchar, commachar);
}
fmt_radix(colon, atsign)
{
int radix, mincol, padchar, commachar;
object x;
int i, j, k;
int s, t;
bool b;
extern (*write_ch_fun)(), writec_PRINTstream();
if (fmt_nparam == 0) {
x = fmt_advance();
check_type_integer(&x);
if (atsign) {
if (type_of(x) == t_fixnum)
i = fix(x);
else
i = -1;
if (!colon && (i <= 0 || i >= 4000) ||
colon && (i <= 0 || i >= 5000)) {
fmt_integer(x, FALSE, FALSE, 10, 0, ' ', ',');
return;
}
fmt_roman(i/1000, 'M', '*', '*', colon);
fmt_roman(i%1000/100, 'C', 'D', 'M', colon);
fmt_roman(i%100/10, 'X', 'L', 'C', colon);
fmt_roman(i%10, 'I', 'V', 'X', colon);
return;
}
fmt_temporary_string->st.st_fillp = 0;
fmt_temporary_stream->sm.sm_int0 = file_column(fmt_stream);
fmt_temporary_stream->sm.sm_int1 = file_column(fmt_stream);
PRINTstream = fmt_temporary_stream;
PRINTradix = FALSE;
PRINTbase = 10;
write_ch_fun = writec_PRINTstream;
write_object(x, 0);
s = 0;
i = fmt_temporary_string->st.st_fillp;
if (i == 1 && fmt_tempstr(s) == '0') {
writestr_stream("zero", fmt_stream);
if (colon)
writestr_stream("th", fmt_stream);
return;
} else if (fmt_tempstr(s) == '-') {
writestr_stream("minus ", fmt_stream);
--i;
s++;
}
t = fmt_temporary_string->st.st_fillp;
for (;;)
if (fmt_tempstr(--t) != '0')
break;
for (b = FALSE; i > 0; i -= j) {
b = fmt_nonillion(s, j = (i+29)%30+1, b,
i<=30&&colon, t);
s += j;
if (b && i > 30) {
for (k = (i - 1)/30; k > 0; --k)
writestr_stream(" nonillion",
fmt_stream);
if (colon && s > t)
writestr_stream("th", fmt_stream);
}
}
return;
}
fmt_max_param(4);
fmt_set_param(0, &radix, INT, 10);
fmt_set_param(1, &mincol, INT, 0);
fmt_set_param(2, &padchar, CHAR, ' ');
fmt_set_param(3, &commachar, CHAR, ',');
x = fmt_advance();
check_type_integer(&x);
if (radix < 0 || radix > 36) {
vs_push(make_fixnum(radix));
FEerror("~D is illegal as a radix.", 1, vs_head);
}
fmt_integer(x, colon, atsign, radix, mincol, padchar, commachar);
}
fmt_integer(x, colon, atsign, radix, mincol, padchar, commachar)
object x;
{
int l, l1;
int s;
extern (*write_ch_fun)(), writec_PRINTstream();
if (type_of(x) != t_fixnum && type_of(x) != t_bignum) {
fmt_temporary_string->st.st_fillp = 0;
fmt_temporary_stream->sm.sm_int0 = file_column(fmt_stream);
fmt_temporary_stream->sm.sm_int1 = file_column(fmt_stream);
setupPRINTdefault(x);
PRINTstream = fmt_temporary_stream;
PRINTescape = FALSE;
PRINTbase = radix;
write_ch_fun = writec_PRINTstream;
write_object(x, 0);
cleanupPRINT();
l = fmt_temporary_string->st.st_fillp;
mincol -= l;
while (mincol-- > 0)
writec_stream(padchar, fmt_stream);
for (s = 0; l > 0; --l, s++)
writec_stream(fmt_tempstr(s), fmt_stream);
return;
}
fmt_temporary_string->st.st_fillp = 0;
fmt_temporary_stream->sm.sm_int0 = file_column(fmt_stream);
fmt_temporary_stream->sm.sm_int1 = file_column(fmt_stream);
PRINTstream = fmt_temporary_stream;
PRINTradix = FALSE;
PRINTbase = radix;
write_ch_fun = writec_PRINTstream;
write_object(x, 0);
l = l1 = fmt_temporary_string->st.st_fillp;
s = 0;
if (fmt_tempstr(s) == '-')
--l1;
mincol -= l;
if (colon)
mincol -= (l1 - 1)/3;
if (atsign && fmt_tempstr(s) != '-')
--mincol;
while (mincol-- > 0)
writec_stream(padchar, fmt_stream);
if (fmt_tempstr(s) == '-') {
s++;
writec_stream('-', fmt_stream);
} else if (atsign)
writec_stream('+', fmt_stream);
while (l1-- > 0) {
writec_stream(fmt_tempstr(s++), fmt_stream);
if (colon && l1 > 0 && l1%3 == 0)
writec_stream(commachar, fmt_stream);
}
}
fmt_nonillion(s, i, b, o, t)
int s, t;
int i;
bool b, o;
{
int j;
for (; i > 3; i -= j) {
b = fmt_thousand(s, j = (i+2)%3+1, b, FALSE, t);
if (j != 3 || fmt_tempstr(s) != '0' ||
fmt_tempstr(s+1) != '0' || fmt_tempstr(s+2) != '0') {
writec_stream(' ', fmt_stream);
writestr_stream(fmt_big_numeral[(i - 1)/3 - 1],
fmt_stream);
s += j;
if (o && s > t)
writestr_stream("th", fmt_stream);
} else
s += j;
}
return(fmt_thousand(s, i, b, o, t));
}
fmt_thousand(s, i, b, o, t)
int s, t;
int i;
bool b, o;
{
if (i == 3 && fmt_tempstr(s) > '0') {
if (b)
writec_stream(' ', fmt_stream);
fmt_write_numeral(s, 0);
writestr_stream(" hundred", fmt_stream);
--i;
s++;
b = TRUE;
if (o & s > t)
writestr_stream("th", fmt_stream);
}
if (i == 3) {
--i;
s++;
}
if (i == 2 && fmt_tempstr(s) > '0') {
if (b)
writec_stream(' ', fmt_stream);
if (fmt_tempstr(s) == '1') {
if (o && s + 2 > t)
fmt_write_ordinal(++s, 10);
else
fmt_write_numeral(++s, 10);
return(TRUE);
} else {
if (o && s + 1 > t)
fmt_write_ordinal(s, 20);
else
fmt_write_numeral(s, 20);
s++;
if (fmt_tempstr(s) > '0') {
writec_stream('-', fmt_stream);
if (o && s + 1 > t)
fmt_write_ordinal(s, 0);
else
fmt_write_numeral(s, 0);
}
return(TRUE);
}
}
if (i == 2)
s++;
if (fmt_tempstr(s) > '0') {
if (b)
writec_stream(' ', fmt_stream);
if (o && s + 1 > t)
fmt_write_ordinal(s, 0);
else
fmt_write_numeral(s, 0);
return(TRUE);
}
return(b);
}
fmt_write_numeral(s, i)
int s, i;
{
writestr_stream(fmt_numeral[fmt_tempstr(s) - '0' + i], fmt_stream);
}
fmt_write_ordinal(s, i)
int s, i;
{
writestr_stream(fmt_ordinal[fmt_tempstr(s) - '0' + i], fmt_stream);
}
fmt_roman(i, one, five, ten, colon)
{
int j;
if (i == 0)
return;
if (!colon && i < 4 || colon && i < 5)
for (j = 0; j < i; j++)
writec_stream(one, fmt_stream);
else if (!colon && i == 4) {
writec_stream(one, fmt_stream);
writec_stream(five, fmt_stream);
} else if (!colon && i < 9 || colon) {
writec_stream(five, fmt_stream);
for (j = 5; j < i; j++)
writec_stream(one, fmt_stream);
} else if (!colon && i == 9) {
writec_stream(one, fmt_stream);
writec_stream(ten, fmt_stream);
}
}
fmt_plural(colon, atsign)
{
fmt_max_param(0);
if (colon) {
if (fmt_index == 0)
fmt_error("can't back up");
--fmt_index;
}
if (eql(fmt_advance(), make_fixnum(1)))
if (atsign)
writec_stream('y', fmt_stream);
else
;
else
if (atsign)
writestr_stream("ies", fmt_stream);
else
writec_stream('s', fmt_stream);
}
fmt_character(colon, atsign)
{
object x;
int i;
fmt_max_param(0);
fmt_temporary_string->st.st_fillp = 0;
fmt_temporary_stream->sm.sm_int0 = 0;
fmt_temporary_stream->sm.sm_int1 = 0;
x = fmt_advance();
check_type_character(&x);
prin1(x, fmt_temporary_stream);
if (!colon && atsign)
i = 0;
else
i = 2;
for (; i < fmt_temporary_string->st.st_fillp; i++)
writec_stream(fmt_tempstr(i), fmt_stream);
}
fmt_fix_float(colon, atsign)
{
int w, d, k, overflowchar, padchar;
double f;
int sign;
char buff[256], *b, buff1[256];
int exp;
int i, j;
object x;
int n, m;
vs_mark;
b = buff1 + 1;
fmt_not_colon(colon);
fmt_max_param(5);
fmt_set_param(0, &w, INT, 0);
if (w < 0)
fmt_error("illegal width");
fmt_set_param(0, &w, INT, -1);
fmt_set_param(1, &d, INT, 0);
if (d < 0)
fmt_error("illegal number of digits");
fmt_set_param(1, &d, INT, -1);
fmt_set_param(2, &k, INT, 0);
fmt_set_param(3, &overflowchar, CHAR, -1);
fmt_set_param(4, &padchar, CHAR, ' ');
x = fmt_advance();
if (type_of(x) == t_fixnum ||
type_of(x) == t_bignum ||
type_of(x) == t_ratio) {
x = make_shortfloat((shortfloat)number_to_double(x));
vs_push(x);
}
if (type_of(x) == t_complex) {
if (w < 0)
prin1(x, fmt_stream);
else {
fmt_nparam = 1;
--fmt_index;
fmt_decimal(colon, atsign);
}
vs_reset;
return;
}
if (type_of(x) == t_longfloat)
n = 16;
else
n = 7;
f = number_to_double(x);
edit_double(n, f, &sign, buff, &exp);
if (exp + k > 100 || exp + k < -100 || d > 100) {
prin1(x, fmt_stream);
vs_reset;
return;
}
if (d >= 0)
m = d + exp + k + 1;
else if (w >= 0) {
if (exp + k >= 0)
m = w - 1;
else
m = w + exp + k - 2;
if (sign < 0 || atsign)
--m;
if (m == 0)
m = 1;
} else
m = n;
if (m <= 0) {
if (m == 0 && buff[0] >= '5') {
exp++;
n = m = 1;
buff[0] = '1';
} else
n = m = 0;
} else if (m < n) {
n = m;
edit_double(n, f, &sign, buff, &exp);
}
while (n >= 0)
if (buff[n - 1] == '0')
--n;
else
break;
exp += k;
j = 0;
if (exp >= 0) {
for (i = 0; i <= exp; i++)
b[j++] = i < n ? buff[i] : '0';
b[j++] = '.';
if (d >= 0)
for (m = i + d; i < m; i++)
b[j++] = i < n ? buff[i] : '0';
else
for (; i < n; i++)
b[j++] = buff[i];
} else {
b[j++] = '.';
if (d >= 0) {
for (i = 0; i < (-exp) - 1 && i < d; i++)
b[j++] = '0';
for (m = d - i, i = 0; i < m; i++)
b[j++] = i < n ? buff[i] : '0';
} else if (n > 0) {
for (i = 0; i < (-exp) - 1; i++)
b[j++] = '0';
for (i = 0; i < n; i++)
b[j++] = buff[i];
}
}
b[j] = '\0';
if (w >= 0) {
if (sign < 0 || atsign)
--w;
if (j > w && overflowchar >= 0)
goto OVER;
if (j < w && b[j-1] == '.') {
b[j++] = '0';
b[j] = '\0';
}
if (j < w && b[0] == '.') {
*--b = '0';
j++;
}
for (i = j; i < w; i++)
writec_stream(padchar, fmt_stream);
} else {
if (b[0] == '.') {
*--b = '0';
j++;
}
if (d < 0 && b[j-1] == '.') {
b[j++] = '0';
b[j] = '\0';
}
}
if (sign < 0)
writec_stream('-', fmt_stream);
else if (atsign)
writec_stream('+', fmt_stream);
writestr_stream(b, fmt_stream);
vs_reset;
return;
OVER:
fmt_set_param(0, &w, INT, 0);
for (i = 0; i < w; i++)
writec_stream(overflowchar, fmt_stream);
vs_reset;
return;
}
int
fmt_exponent_length(e)
{
int i;
if (e == 0)
return(1);
if (e < 0)
e = -e;
for (i = 0; e > 0; i++, e /= 10)
;
return(i);
}
fmt_exponent(e)
{
if (e == 0) {
writec_stream('0', fmt_stream);
return;
}
if (e < 0)
e = -e;
fmt_exponent1(e);
}
fmt_exponent1(e)
{
if (e == 0)
return;
fmt_exponent1(e/10);
writec_stream('0' + e%10, fmt_stream);
}
fmt_exponential_float(colon, atsign)
{
int w, d, e, k, overflowchar, padchar, exponentchar;
double f;
int sign;
char buff[256], *b, buff1[256];
int exp;
int i, j;
object x, y;
int n, m;
enum type t;
vs_mark;
b = buff1 + 1;
fmt_not_colon(colon);
fmt_max_param(7);
fmt_set_param(0, &w, INT, 0);
if (w < 0)
fmt_error("illegal width");
fmt_set_param(0, &w, INT, -1);
fmt_set_param(1, &d, INT, 0);
if (d < 0)
fmt_error("illegal number of digits");
fmt_set_param(1, &d, INT, -1);
fmt_set_param(2, &e, INT, 0);
if (e < 0)
fmt_error("illegal number of digits in exponent");
fmt_set_param(2, &e, INT, -1);
fmt_set_param(3, &k, INT, 1);
fmt_set_param(4, &overflowchar, CHAR, -1);
fmt_set_param(5, &padchar, CHAR, ' ');
fmt_set_param(6, &exponentchar, CHAR, -1);
x = fmt_advance();
if (type_of(x) == t_fixnum ||
type_of(x) == t_bignum ||
type_of(x) == t_ratio) {
x = make_shortfloat((shortfloat)number_to_double(x));
vs_push(x);
}
if (type_of(x) == t_complex) {
if (w < 0)
prin1(x, fmt_stream);
else {
fmt_nparam = 1;
--fmt_index;
fmt_decimal(colon, atsign);
}
vs_reset;
return;
}
if (type_of(x) == t_longfloat)
n = 16;
else
n = 7;
f = number_to_double(x);
edit_double(n, f, &sign, buff, &exp);
if (d >= 0) {
if (k > 0) {
if (!(k < d + 2))
fmt_error("illegal scale factor");
m = d + 1;
} else {
if (!(k > -d))
fmt_error("illegal scale factor");
m = d + k;
}
} else if (w >= 0) {
if (k > 0)
m = w - 1;
else
m = w + k - 1;
if (sign < 0 || atsign)
--m;
if (e >= 0)
m -= e + 2;
else
m -= fmt_exponent_length(e - k + 1) + 2;
} else
m = n;
if (m <= 0) {
if (m == 0 && buff[0] >= '5') {
exp++;
n = m = 1;
buff[0] = '1';
} else
n = m = 0;
} else if (m < n) {
n = m;
edit_double(n, f, &sign, buff, &exp);
}
while (n >= 0)
if (buff[n - 1] == '0')
--n;
else
break;
exp = exp - k + 1;
j = 0;
if (k > 0) {
for (i = 0; i < k; i++)
b[j++] = i < n ? buff[i] : '0';
b[j++] = '.';
if (d >= 0)
for (m = i + (d - k + 1); i < m; i++)
b[j++] = i < n ? buff[i] : '0';
else
for (; i < n; i++)
b[j++] = buff[i];
} else {
b[j++] = '.';
if (d >= 0) {
for (i = 0; i < -k && i < d; i++)
b[j++] = '0';
for (m = d - i, i = 0; i < m; i++)
b[j++] = i < n ? buff[i] : '0';
} else if (n > 0) {
for (i = 0; i < -k; i++)
b[j++] = '0';
for (i = 0; i < n; i++)
b[j++] = buff[i];
}
}
b[j] = '\0';
if (w >= 0) {
if (sign < 0 || atsign)
--w;
i = fmt_exponent_length(exp);
if (e >= 0) {
if (i > e) {
if (overflowchar >= 0)
goto OVER;
else
e = i;
}
w -= e + 2;
} else
w -= i + 2;
if (j > w && overflowchar >= 0)
goto OVER;
if (j < w && b[j-1] == '.') {
b[j++] = '0';
b[j] = '\0';
}
if (j < w && b[0] == '.') {
*--b = '0';
j++;
}
for (i = j; i < w; i++)
writec_stream(padchar, fmt_stream);
} else {
if (b[j-1] == '.') {
b[j++] = '0';
b[j] = '\0';
}
if (d < 0 && b[0] == '.') {
*--b = '0';
j++;
}
}
if (sign < 0)
writec_stream('-', fmt_stream);
else if (atsign)
writec_stream('+', fmt_stream);
writestr_stream(b, fmt_stream);
y = symbol_value(Vread_default_float_format);
if (exponentchar < 0) {
if (y == Slong_float || y == Sdouble_float)
t = t_longfloat;
else
t = t_shortfloat;
if (type_of(x) == t)
exponentchar = 'E';
else if (type_of(x) == t_shortfloat)
exponentchar = 'S';
else
exponentchar = 'L';
}
writec_stream(exponentchar, fmt_stream);
if (exp < 0)
writec_stream('-', fmt_stream);
else
writec_stream('+', fmt_stream);
if (e >= 0)
for (i = e - fmt_exponent_length(exp); i > 0; --i)
writec_stream('0', fmt_stream);
fmt_exponent(exp);
vs_reset;
return;
OVER:
fmt_set_param(0, &w, INT, -1);
for (i = 0; i < w; i++)
writec_stream(overflowchar, fmt_stream);
vs_reset;
return;
}
fmt_general_float(colon, atsign)
{
int w, d, e, k, overflowchar, padchar, exponentchar;
int sign, exp;
char buff[256];
object x;
int n, ee, ww, q, dd;
vs_mark;
fmt_not_colon(colon);
fmt_max_param(7);
fmt_set_param(0, &w, INT, 0);
if (w < 0)
fmt_error("illegal width");
fmt_set_param(0, &w, INT, -1);
fmt_set_param(1, &d, INT, 0);
if (d < 0)
fmt_error("illegal number of digits");
fmt_set_param(1, &d, INT, -1);
fmt_set_param(2, &e, INT, 0);
if (e < 0)
fmt_error("illegal number of digits in exponent");
fmt_set_param(2, &e, INT, -1);
fmt_set_param(3, &k, INT, 1);
fmt_set_param(4, &overflowchar, CHAR, -1);
fmt_set_param(5, &padchar, CHAR, ' ');
fmt_set_param(6, &exponentchar, CHAR, -1);
x = fmt_advance();
if (type_of(x) == t_complex) {
if (w < 0)
prin1(x, fmt_stream);
else {
fmt_nparam = 1;
--fmt_index;
fmt_decimal(colon, atsign);
}
vs_reset;
return;
}
if (type_of(x) == t_longfloat)
q = 16;
else
q = 7;
edit_double(q, number_to_double(x), &sign, buff, &exp);
n = exp + 1;
while (q >= 0)
if (buff[q - 1] == '0')
--q;
else
break;
if (e >= 0)
ee = e + 2;
else
ee = 4;
ww = w - ee;
if (d < 0) {
d = n < 7 ? n : 7;
d = q > d ? q : d;
}
dd = d - n;
if (0 <= dd && dd <= d) {
fmt_nparam = 5;
fmt_param[0].fmt_param_value = ww;
fmt_param[1].fmt_param_value = dd;
fmt_param[1].fmt_param_type = INT;
fmt_param[2].fmt_param_type = NULL;
fmt_param[3] = fmt_param[4];
fmt_param[4] = fmt_param[5];
--fmt_index;
fmt_fix_float(colon, atsign);
if (w >= 0)
while (ww++ < w)
writec_stream(padchar, fmt_stream);
vs_reset;
return;
}
fmt_param[1].fmt_param_value = d;
fmt_param[1].fmt_param_type = INT;
--fmt_index;
fmt_exponential_float(colon, atsign);
vs_reset;
}
fmt_dollars_float(colon, atsign)
{
int d, n, w, padchar;
double f;
int sign;
char buff[256];
int exp;
int q, i;
object x;
vs_mark;
fmt_max_param(4);
fmt_set_param(0, &d, INT, 2);
if (d < 0)
fmt_error("illegal number of digits");
fmt_set_param(1, &n, INT, 1);
if (n < 0)
fmt_error("illegal number of digits");
fmt_set_param(2, &w, INT, 0);
if (w < 0)
fmt_error("illegal width");
fmt_set_param(3, &padchar, CHAR, ' ');
x = fmt_advance();
if (type_of(x) == t_complex) {
if (w < 0)
prin1(x, fmt_stream);
else {
fmt_nparam = 1;
fmt_param[0] = fmt_param[2];
--fmt_index;
fmt_decimal(colon, atsign);
}
vs_reset;
return;
}
q = 7;
if (type_of(x) == t_longfloat)
q = 16;
f = number_to_double(x);
edit_double(q, f, &sign, buff, &exp);
if ((q = exp + d + 1) > 0)
edit_double(q, f, &sign, buff, &exp);
exp++;
if (w > 100 || exp > 100 || exp < -100) {
fmt_nparam = 6;
fmt_param[0] = fmt_param[2];
fmt_param[1].fmt_param_value = d + n - 1;
fmt_param[1].fmt_param_type = INT;
fmt_param[2].fmt_param_type =
fmt_param[3].fmt_param_type =
fmt_param[4].fmt_param_type = NULL;
fmt_param[5] = fmt_param[3];
--fmt_index;
fmt_exponential_float(colon, atsign);
}
if (exp > n)
n = exp;
if (sign < 0 || atsign)
--w;
if (colon) {
if (sign < 0)
writec_stream('-', fmt_stream);
else if (atsign)
writec_stream('+', fmt_stream);
while (--w > n + d)
writec_stream(padchar, fmt_stream);
} else {
while (--w > n + d)
writec_stream(padchar, fmt_stream);
if (sign < 0)
writec_stream('-', fmt_stream);
else if (atsign)
writec_stream('+', fmt_stream);
}
for (i = n - exp; i > 0; --i)
writec_stream('0', fmt_stream);
for (i = 0; i < exp; i++)
writec_stream((i < q ? buff[i] : '0'), fmt_stream);
writec_stream('.', fmt_stream);
for (d += i; i < d; i++)
writec_stream((i < q ? buff[i] : '0'), fmt_stream);
vs_reset;
}
fmt_percent(colon, atsign)
{
int n, i;
fmt_max_param(1);
fmt_set_param(0, &n, INT, 1);
fmt_not_colon(colon);
fmt_not_atsign(atsign);
while (n-- > 0) {
writec_stream('\n', fmt_stream);
if (n == 0)
for (i = fmt_indents; i > 0; --i)
writec_stream(' ', fmt_stream);
}
}
fmt_ampersand(colon, atsign)
{
int n;
fmt_max_param(1);
fmt_set_param(0, &n, INT, 1);
fmt_not_colon(colon);
fmt_not_atsign(atsign);
if (n == 0)
return;
if (file_column(fmt_stream) != 0)
writec_stream('\n', fmt_stream);
while (--n > 0)
writec_stream('\n', fmt_stream);
fmt_indents = 0;
}
fmt_bar(colon, atsign)
{
int n;
fmt_max_param(1);
fmt_set_param(0, &n, INT, 1);
fmt_not_colon(colon);
fmt_not_atsign(atsign);
while (n-- > 0)
writec_stream('\f', fmt_stream);
}
fmt_tilde(colon, atsign)
{
int n;
fmt_max_param(1);
fmt_set_param(0, &n, INT, 1);
fmt_not_colon(colon);
fmt_not_atsign(atsign);
while (n-- > 0)
writec_stream('~', fmt_stream);
}
fmt_newline(colon, atsign)
{
int c;
fmt_max_param(0);
fmt_not_colon_atsign(colon, atsign);
if (atsign)
writec_stream('\n', fmt_stream);
while (ctl_index < ctl_end && isspace(ctl_string[ctl_index])) {
if (colon)
writec_stream(ctl_string[ctl_index], fmt_stream);
ctl_index++;
}
}
fmt_tabulate(colon, atsign)
{
int colnum, colinc;
int c, i;
fmt_max_param(2);
fmt_not_colon(colon);
fmt_set_param(0, &colnum, INT, 1);
fmt_set_param(1, &colinc, INT, 1);
if (!atsign) {
c = file_column(fmt_stream);
if (c < 0) {
writestr_stream(" ", fmt_stream);
return;
}
if (c > colnum && colinc <= 0)
return;
while (c > colnum)
colnum += colinc;
for (i = colnum - c; i > 0; --i)
writec_stream(' ', fmt_stream);
} else {
for (i = colnum; i > 0; --i)
writec_stream(' ', fmt_stream);
c = file_column(fmt_stream);
if (c < 0 || colinc <= 0)
return;
colnum = 0;
while (c > colnum)
colnum += colinc;
for (i = colnum - c; i > 0; --i)
writec_stream(' ', fmt_stream);
}
}
fmt_asterisk(colon, atsign)
{
int n;
fmt_max_param(1);
fmt_not_colon_atsign(colon, atsign);
if (atsign) {
fmt_set_param(0, &n, INT, 0);
if (n < 0 || n >= fmt_end)
fmt_error("can't goto");
fmt_index = n;
} else if (colon) {
fmt_set_param(0, &n, INT, 1);
if (n > fmt_index)
fmt_error("can't back up");
fmt_index -= n;
} else {
fmt_set_param(0, &n, INT, 1);
while (n-- > 0)
fmt_advance();
}
}
fmt_indirection(colon, atsign)
{
object s, l;
fmt_old;
jmp_buf fmt_jmp_buf0;
int up_colon;
fmt_max_param(0);
fmt_not_colon(colon);
s = fmt_advance();
if (type_of(s) != t_string)
fmt_error("control string expected");
if (atsign) {
fmt_save;
fmt_jmp_buf = fmt_jmp_buf0;
fmt_string = s;
if (up_colon = setjmp(fmt_jmp_buf)) {
if (--up_colon)
fmt_error("illegal ~:^");
} else
format(fmt_stream, 0, s->st.st_fillp);
fmt_restore1;
} else {
l = fmt_advance();
fmt_save;
fmt_base = vs_top;
fmt_index = 0;
for (fmt_end = 0; !endp(l); fmt_end++, l = l->c.c_cdr)
vs_check_push(l->c.c_car);
fmt_jmp_buf = fmt_jmp_buf0;
fmt_string = s;
if (up_colon = setjmp(fmt_jmp_buf)) {
if (--up_colon)
fmt_error("illegal ~:^");
} else
format(fmt_stream, 0, s->st.st_fillp);
vs_top = fmt_base;
fmt_restore;
}
}
fmt_case(colon, atsign)
{
object x;
int i, j;
fmt_old;
jmp_buf fmt_jmp_buf0;
int up_colon;
bool b;
x = make_string_output_stream(64);
vs_push(x);
i = ctl_index;
j = fmt_skip();
if (ctl_string[--j] != ')' || ctl_string[--j] != '~')
fmt_error("~) expected");
fmt_save;
fmt_jmp_buf = fmt_jmp_buf0;
if (up_colon = setjmp(fmt_jmp_buf))
;
else
format(x, ctl_origin + i, j - i);
fmt_restore1;
x = x->sm.sm_object0;
if (!colon && !atsign)
for (i = 0; i < x->st.st_fillp; i++) {
if (isUpper(j = x->st.st_self[i]))
j += 'a' - 'A';
writec_stream(j, fmt_stream);
}
else if (colon && !atsign)
for (b = TRUE, i = 0; i < x->st.st_fillp; i++) {
if (isLower(j = x->st.st_self[i])) {
if (b)
j -= 'a' - 'A';
b = FALSE;
} else if (isUpper(j)) {
if (!b)
j += 'a' - 'A';
b = FALSE;
} else if (!isDigit(j))
b = TRUE;
writec_stream(j, fmt_stream);
}
else if (!colon && atsign)
for (b = TRUE, i = 0; i < x->st.st_fillp; i++) {
if (isLower(j = x->st.st_self[i])) {
if (b)
j -= 'a' - 'A';
b = FALSE;
} else if (isUpper(j)) {
if (!b)
j += 'a' - 'A';
b = FALSE;
}
writec_stream(j, fmt_stream);
}
else
for (i = 0; i < x->st.st_fillp; i++) {
if (isLower(j = x->st.st_self[i]))
j -= 'a' - 'A';
writec_stream(j, fmt_stream);
}
vs_pop;
if (up_colon)
longjmp(fmt_jmp_buf, up_colon);
}
fmt_conditional(colon, atsign)
{
int i, j, k;
object x;
int n;
bool done;
fmt_old;
fmt_not_colon_atsign(colon, atsign);
if (colon) {
fmt_max_param(0);
i = ctl_index;
j = fmt_skip();
if (ctl_string[--j] != ';' || ctl_string[--j] != '~')
fmt_error("~; expected");
k = fmt_skip();
if (ctl_string[--k] != ']' || ctl_string[--k] != '~')
fmt_error("~] expected");
if (fmt_advance() == Cnil) {
fmt_save;
format(fmt_stream, ctl_origin + i, j - i);
fmt_restore1;
} else {
fmt_save;
format(fmt_stream, ctl_origin + j + 2, k - (j + 2));
fmt_restore1;
}
} else if (atsign) {
i = ctl_index;
j = fmt_skip();
if (ctl_string[--j] != ']' || ctl_string[--j] != '~')
fmt_error("~] expected");
if (fmt_advance() == Cnil)
;
else {
--fmt_index;
fmt_save;
format(fmt_stream, ctl_origin + i, j - i);
fmt_restore1;
}
} else {
fmt_max_param(1);
if (fmt_nparam == 0) {
x = fmt_advance();
if (type_of(x) != t_fixnum)
fmt_error("illegal argument for conditional");
n = fix(x);
} else
fmt_set_param(0, &n, INT, 0);
i = ctl_index;
for (done = FALSE;; --n) {
j = fmt_skip();
for (k = j; ctl_string[--k] != '~';)
;
if (n == 0) {
fmt_save;
format(fmt_stream, ctl_origin + i, k - i);
fmt_restore1;
done = TRUE;
}
i = j;
if (ctl_string[--j] == ']') {
if (ctl_string[--j] != '~')
fmt_error("~] expected");
return;
}
if (ctl_string[j] == ';') {
if (ctl_string[--j] == '~')
continue;
if (ctl_string[j] == ':')
goto ELSE;
}
fmt_error("~; or ~] expected");
}
ELSE:
if (ctl_string[--j] != '~')
fmt_error("~:; expected");
j = fmt_skip();
if (ctl_string[--j] != ']' || ctl_string[--j] != '~')
fmt_error("~] expected");
if (!done) {
fmt_save;
format(fmt_stream, ctl_origin + i, j - i);
fmt_restore1;
}
}
}
fmt_iteration(colon, atsign)
{
int n;
int i, j;
int o;
bool colon_close = FALSE;
object l, l0;
fmt_old;
jmp_buf fmt_jmp_buf0;
int up_colon;
fmt_max_param(1);
fmt_set_param(0, &n, INT, 1000000);
i = ctl_index;
j = fmt_skip();
if (ctl_string[--j] != '}')
fmt_error("~} expected");
if (ctl_string[--j] == ':') {
colon_close = TRUE;
--j;
}
if (ctl_string[j] != '~')
fmt_error("syntax error");
o = ctl_origin;
if (!colon && !atsign) {
l = fmt_advance();
fmt_save;
fmt_base = vs_top;
fmt_index = 0;
for (fmt_end = 0; !endp(l); fmt_end++, l = l->c.c_cdr)
vs_check_push(l->c.c_car);
fmt_jmp_buf = fmt_jmp_buf0;
if (colon_close)
goto L1;
while (fmt_index < fmt_end) {
L1:
if (n-- <= 0)
break;
if (up_colon = setjmp(fmt_jmp_buf)) {
if (--up_colon)
fmt_error("illegal ~:^");
break;
}
format(fmt_stream, o + i, j - i);
}
vs_top = fmt_base;
fmt_restore;
} else if (colon && !atsign) {
l0 = fmt_advance();
fmt_save;
fmt_base = vs_top;
fmt_jmp_buf = fmt_jmp_buf0;
if (colon_close)
goto L2;
while (!endp(l0)) {
L2:
if (n-- <= 0)
break;
l = l0->c.c_car;
l0 = l0->c.c_cdr;
fmt_index = 0;
for (fmt_end = 0; !endp(l); fmt_end++, l = l->c.c_cdr)
vs_check_push(l->c.c_car);
if (up_colon = setjmp(fmt_jmp_buf)) {
vs_top = fmt_base;
if (--up_colon)
break;
else
continue;
}
format(fmt_stream, o + i, j - i);
vs_top = fmt_base;
}
fmt_restore;
} else if (!colon && atsign) {
fmt_save;
fmt_jmp_buf = fmt_jmp_buf0;
if (colon_close)
goto L3;
while (fmt_index < fmt_end) {
L3:
if (n-- <= 0)
break;
if (up_colon = setjmp(fmt_jmp_buf)) {
if (--up_colon)
fmt_error("illegal ~:^");
break;
}
format(fmt_stream, o + i, j - i);
}
fmt_restore1;
} else if (colon && atsign) {
if (colon_close)
goto L4;
while (fmt_index < fmt_end) {
L4:
if (n-- <= 0)
break;
l = fmt_advance();
fmt_save;
fmt_base = vs_top;
fmt_index = 0;
for (fmt_end = 0; !endp(l); fmt_end++, l = l->c.c_cdr)
vs_check_push(l->c.c_car);
fmt_jmp_buf = fmt_jmp_buf0;
if (up_colon = setjmp(fmt_jmp_buf)) {
vs_top = fmt_base;
fmt_restore;
if (--up_colon)
break;
else
continue;
}
format(fmt_stream, o + i, j - i);
vs_top = fmt_base;
fmt_restore;
}
}
}
fmt_justification(colon, atsign)
{
int mincol, colinc, minpad, padchar;
object fields[16];
fmt_old;
jmp_buf fmt_jmp_buf0;
int i, j, k, l, m, n, j0, l0;
int up_colon;
int special = 0;
int spare_spaces, line_length;
vs_mark;
fmt_max_param(4);
fmt_set_param(0, &mincol, INT, 0);
fmt_set_param(1, &colinc, INT, 1);
fmt_set_param(2, &minpad, INT, 0);
fmt_set_param(3, &padchar, CHAR, ' ');
n = 0;
for (;;) {
if (n >= 16)
fmt_error("too many fields");
i = ctl_index;
j0 = j = fmt_skip();
while (ctl_string[--j] != '~')
;
fields[n] = make_string_output_stream(64);
vs_push(fields[n]);
fmt_save;
fmt_jmp_buf = fmt_jmp_buf0;
if (up_colon = setjmp(fmt_jmp_buf)) {
--n;
if (--up_colon)
fmt_error("illegal ~:^");
fmt_restore1;
while (ctl_string[--j0] != '>')
j0 = fmt_skip();
if (ctl_string[--j0] != '~')
fmt_error("~> expected");
break;
}
format(fields[n++], ctl_origin + i, j - i);
fmt_restore1;
if (ctl_string[--j0] == '>') {
if (ctl_string[--j0] != '~')
fmt_error("~> expected");
break;
} else if (ctl_string[j0] != ';')
fmt_error("~; expected");
else if (ctl_string[--j0] == ':') {
if (n != 1)
fmt_error("illegal ~:;");
special = 1;
for (j = j0; ctl_string[j] != '~'; --j)
;
fmt_save;
format(fmt_stream, ctl_origin + j, j0 - j + 2);
fmt_restore1;
spare_spaces = fmt_spare_spaces;
line_length = fmt_line_length;
} else if (ctl_string[j0] != '~')
fmt_error("~; expected");
}
for (i = special, l = 0; i < n; i++)
l += fields[i]->sm.sm_object0->st.st_fillp;
m = n - 1 - special;
if (m <= 0 && !colon && !atsign) {
m = 0;
colon = TRUE;
}
if (colon)
m++;
if (atsign)
m++;
l0 = l;
l += minpad * m;
for (k = 0; mincol + k * colinc < l; k++)
;
l = mincol + k * colinc;
if (special != 0 &&
file_column(fmt_stream) + l + spare_spaces >= line_length)
princ(fields[0]->sm.sm_object0, fmt_stream);
l -= l0;
for (i = special; i < n; i++) {
if (i > 0 || colon)
for (j = l / m, l -= j, --m; j > 0; --j)
writec_stream(padchar, fmt_stream);
princ(fields[i]->sm.sm_object0, fmt_stream);
}
if (atsign)
for (j = l; j > 0; --j)
writec_stream(padchar, fmt_stream);
vs_reset;
}
fmt_up_and_out(colon, atsign)
{
int i, j, k;
fmt_max_param(3);
fmt_not_atsign(atsign);
if (fmt_nparam == 0) {
if (fmt_index >= fmt_end)
longjmp(fmt_jmp_buf, ++colon);
} else if (fmt_nparam == 1) {
fmt_set_param(0, &i, INT, 0);
if (i == 0)
longjmp(fmt_jmp_buf, ++colon);
} else if (fmt_nparam == 2) {
fmt_set_param(0, &i, INT, 0);
fmt_set_param(1, &j, INT, 0);
if (i == j)
longjmp(fmt_jmp_buf, ++colon);
} else {
fmt_set_param(0, &i, INT, 0);
fmt_set_param(1, &j, INT, 0);
fmt_set_param(2, &k, INT, 0);
if (i <= j && j <= k)
longjmp(fmt_jmp_buf, ++colon);
}
}
fmt_semicolon(colon, atsign)
{
fmt_not_atsign(atsign);
if (!colon)
fmt_error("~:; expected");
fmt_max_param(2);
fmt_set_param(0, &fmt_spare_spaces, INT, 0);
fmt_set_param(1, &fmt_line_length, INT, 72);
}
Lformat()
{
object x = OBJNULL;
jmp_buf fmt_jmp_buf0;
bool colon, e;
fmt_old;
if (vs_top - vs_base < 2)
too_few_arguments();
if (vs_base[0] == Cnil) {
vs_base[0] = make_string_output_stream(64);
x = vs_base[0]->sm.sm_object0;
} else if (vs_base[0] == Ct)
vs_base[0] = symbol_value(Vstandard_output);
else if (type_of(vs_base[0]) == t_string) {
x = vs_base[0];
if (!x->st.st_hasfillp)
FEerror("The string ~S doesn't have a fill-pointer.", 1, x);
vs_base[0] = make_string_output_stream(0);
vs_base[0]->sm.sm_object0 = x;
} else
check_type_stream(&vs_base[0]);
check_type_string(&vs_base[1]);
fmt_save;
frs_push(FRS_PROTECT, Cnil);
if (nlj_active) {
e = TRUE;
goto L;
}
fmt_base = vs_base + 2;
fmt_index = 0;
fmt_end = vs_top - vs_base - 2;
fmt_jmp_buf = fmt_jmp_buf0;
if (symbol_value(siVindent_formatted_output) != Cnil)
fmt_indents = file_column(vs_base[0]);
else
fmt_indents = 0;
fmt_string = vs_base[1];
if (colon = setjmp(fmt_jmp_buf)) {
if (--colon)
fmt_error("illegal ~:^");
vs_base = vs_top;
if (x != OBJNULL)
vs_push(x);
else
vs_push(Cnil);
e = FALSE;
goto L;
}
format(vs_base[0], 0, vs_base[1]->st.st_fillp);
flush_stream(vs_base[0]);
vs_base = vs_top;
if (x != OBJNULL)
vs_push(x);
else
vs_push(Cnil);
e = FALSE;
L:
frs_pop();
fmt_restore;
if (e) {
nlj_active = FALSE;
unwind(nlj_fr, nlj_tag);
}
}
fmt_error(s)
{
vs_push(make_simple_string(s));
vs_push(make_fixnum(&ctl_string[ctl_index] - fmt_string->st.st_self));
FEerror("Format error: ~A.~%~V@TV~%\"~A\"~%",
3, vs_top[-2], vs_top[-1], fmt_string);
}
init_format()
{
fmt_temporary_stream = make_string_output_stream(64);
enter_mark_origin(&fmt_temporary_stream);
fmt_temporary_string = fmt_temporary_stream->sm.sm_object0;
make_function("FORMAT", Lformat);
siVindent_formatted_output
= make_si_special("*INDENT-FORMATTED-OUTPUT*", Cnil);
}